package com.ruoyi.system.controller;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ObjectUtil;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.enums.BookReturnStatus;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.exception.base.BaseException;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.system.domain.Book;
import com.ruoyi.system.domain.LendRecord;
import com.ruoyi.system.domain.UserCollection;
import com.ruoyi.system.domain.vo.LendRecordStatistics;
import com.ruoyi.system.domain.vo.LendRecordVo;
import com.ruoyi.system.service.IBookService;
import com.ruoyi.system.service.ILendRecordService;
import com.ruoyi.system.service.IUserCollectionService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletResponse;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 借还记录Controller
 *
 * @author ruoyi
 * @date 2022-12-08
 */
@RestController
@RequestMapping("/system/record")
public class LendRecordController extends BaseController {
    @Autowired
    private ILendRecordService lendRecordService;

    @Autowired
    private IBookService bookService;

    @Autowired
    private IUserCollectionService userCollectionService;

    /**
     * 查询借还记录列表
     */
    @PreAuthorize("@ss.hasPermi('system:record:list')")
    @GetMapping("/list")
    public TableDataInfo list(LendRecord lendRecord) {
        this.startPage();
        List<LendRecord> list = this.lendRecordService.selectLendRecordList(lendRecord);
        return this.getDataTable(list);
    }

    /**
     * 导出借还记录列表
     */
    @PreAuthorize("@ss.hasPermi('system:record:export')")
    @Log(title = "借还记录", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    public void export(HttpServletResponse response, LendRecord lendRecord) {
        List<LendRecord> list = this.lendRecordService.selectLendRecordList(lendRecord);
        ExcelUtil<LendRecord> util = new ExcelUtil<LendRecord>(LendRecord.class);
        util.exportExcel(response, list, "借还记录数据");
    }


    /**
     * 用户借还记录详情
     */
    @PreAuthorize("@ss.hasPermi('system:record:export')")
    @Log(title = "借还记录", businessType = BusinessType.EXPORT)
    @PostMapping("/statistics/{typeCode}")
    public AjaxResult statistics(@PathVariable String typeCode) {
        List<LendRecordVo> list = this.lendRecordService.selectLendBookRecordList(new LendRecord().setStatus(typeCode));
        Map<String, List<LendRecordVo>> map = list.stream().collect(Collectors.groupingBy(LendRecord::getStatus));
        List<LendRecordVo> lendRecordList = BeanUtil.isEmpty(map.get(typeCode)) ? Collections.emptyList() : map.get(typeCode);
        if (BookReturnStatus.ALL.getCode().equals(typeCode)) {
            lendRecordList = this.lendRecordService.selectLendBookRecordList(new LendRecord());
        }
        return AjaxResult.success(
                LendRecordStatistics.builder()
                        .type(typeCode)
                        .lendRecordList(lendRecordList)
                        .build()
        );
    }

    /**
     * 统计
     */
    @PreAuthorize("@ss.hasPermi('system:record:export')")
    @Log(title = "统计", businessType = BusinessType.EXPORT)
    @GetMapping("/statistics")
    public AjaxResult statisticsTotal() {
        // 借还记录
        List<LendRecord> list = this.lendRecordService.selectLendRecordList(new LendRecord().setSno(SecurityUtils.getUsername()));
        // 收藏数
        List<UserCollection> collections = this.userCollectionService.selectUserCollectionList(new UserCollection());
        Map<String, List<LendRecord>> map = list.stream().collect(Collectors.groupingBy(LendRecord::getStatus));
        return AjaxResult.success(
                MapUtil.builder()
                        .put("lend", BeanUtil.isNotEmpty(map.get(BookReturnStatus.FAIL.getCode())) ? map.get(BookReturnStatus.FAIL.getCode()).size() : 0)
                        .put("borrow", BeanUtil.isNotEmpty(map.get(BookReturnStatus.SUCCESS.getCode())) ? map.get(BookReturnStatus.SUCCESS.getCode()).size() : 0)
                        .put("expire", BeanUtil.isNotEmpty(map.get(BookReturnStatus.EXPIRE.getCode())) ? map.get(BookReturnStatus.EXPIRE.getCode()).size() : 0)
                        .put("collection", collections.size())
                        .put("username", SecurityUtils.getLoginUser().getUser().getNickName())
                        .build()
        );
    }

    /**
     * 获取借还记录详细信息
     */
    @PreAuthorize("@ss.hasPermi('system:record:query')")
    @GetMapping(value = "/{id}")
    public AjaxResult getInfo(@PathVariable("id") Long id) {
        return this.success(this.lendRecordService.selectLendRecordById(id));
    }

    /**
     * 新增借还记录
     */
    @PreAuthorize("@ss.hasPermi('system:record:add')")
    @Log(title = "新增借还记录/借阅书籍", businessType = BusinessType.INSERT)
    @PostMapping
    public AjaxResult add(@RequestBody LendRecord lendRecord) {
        Book book = this.bookService.selectBookById(lendRecord.getBookId());
        lendRecord.setStatus(BookReturnStatus.FAIL.getCode());
        lendRecord.setSno(SecurityUtils.getUsername());
        lendRecord.setLendTime(new Date());
        // 截止时间必须大于借阅时间
        if (ObjectUtil.isAllNotEmpty(lendRecord.getLendTime(), lendRecord.getDeadline())) {
            if (lendRecord.getDeadline().compareTo(lendRecord.getLendTime()) < 0) {
                throw new BaseException("截止时间不能小于借阅时间");
            }
        } else {
            throw new BaseException("截止时间不能为空");
        }
        Assert.notNull(book, "不存在该书籍");
        // 判断是否已经借阅
        List<LendRecord> lendRecords = lendRecordService.selectLendRecordList(
                new LendRecord().setSno(lendRecord.getSno())
                        .setBookId(lendRecord.getBookId())
                        .setStatus(BookReturnStatus.FAIL.getCode()));
        if (CollUtil.isNotEmpty(lendRecords)) {
            throw new BaseException("已借阅该书籍");
        }
        return this.toAjax(this.lendRecordService.insertLendRecord(lendRecord));
    }

    /**
     * 修改借还记录
     */
    @PreAuthorize("@ss.hasPermi('system:record:edit')")
    @Log(title = "编辑借还记录/归还时间", businessType = BusinessType.UPDATE)
    @PutMapping
    public AjaxResult edit(@RequestBody LendRecord params) {
        LendRecord lendRecord = lendRecordService.selectLendRecordById(params.getId());
        Assert.notNull(lendRecord,"数据参数错误");
        lendRecord.setReturnTime(new Date());
        // 如果设置了归还时间表示已经归还
        lendRecord.setStatus(BookReturnStatus.SUCCESS.getCode());
        return this.toAjax(this.lendRecordService.updateLendRecord(lendRecord));
    }

    /**
     * 借书延期
     */
    @PreAuthorize("@ss.hasPermi('system:record:delay')")
    @Log(title = "借书延期", businessType = BusinessType.UPDATE)
    @PostMapping("delay")
    public AjaxResult delay(@RequestBody LendRecord params) {
        LendRecord lendRecord = lendRecordService.selectLendRecordById(params.getId());
        // 归还时间大于借阅时间
        if (ObjectUtil.isAllNotEmpty(params.getDeadline(), lendRecord.getLendTime())) {
            if (params.getDeadline().compareTo(lendRecord.getLendTime()) < 0) {
                throw new BaseException("截止时间不能小于借阅时间");
            }
        } else {
            throw new BaseException("截止时间不能为空");
        }
        lendRecord.setStatus(BookReturnStatus.FAIL.getCode());
        lendRecord.setSno(SecurityUtils.getUsername());
        return this.toAjax(this.lendRecordService.updateLendRecord(lendRecord));
    }


    /**
     * 删除借还记录
     */
    @PreAuthorize("@ss.hasPermi('system:record:remove')")
    @Log(title = "批量删除", businessType = BusinessType.DELETE)
    @DeleteMapping("/{ids}")
    public AjaxResult remove(@PathVariable Long[] ids) {
        return this.toAjax(this.lendRecordService.deleteLendRecordByIds(ids));
    }
}
